package com.example.kotlinstudy.s5

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
import org.junit.Test
import java.io.File

class Test5_标准库函数_flow {
//    标准库函数7种

    @Test
    //标准库函数apply 直接返回接收者对象
    fun test1() {
        val files: File = File("E:/xx.txt")
        files.setWritable(true)
        files.setReadable(true)

        //直接返回接收者对象
        val files2: File = File("E:/xx.txt").apply {
            setWritable(true) //并且这里是隐匿调用，this就指接收者
            setReadable(true)
        }
    }

    @Test
    //标准库函数let
    fun test2() {
        //把接收者传给it
        //会把最后一行返回给
        val result = listOf(3, 2, 1).first().let {
            it * it
        }
        println(result)

        println(formatGreeting(null))
    }

    fun formatGreeting(guestName: String?): String {
        return guestName?.let { "welcome, $it" } ?: "What's your name" // 链式调用 ， let和空的结合使用
    }

    @Test
    //标准库函数run
    //1.光看作用域run和apply差不多，但是不同是run函数不返回接收者，返回的lambda的结果也就是true,false（也就是最后一行执行的结果和let一样，而且还具有apply的隐式调用）
    //2.还可以用来执行函数引用所以很容易执行链式调用  函数的引用两个的冒号 ::加上方法名
    fun test3() {
        //读取文件
        val files: File =
            File("/Volumes/1T/StudioProjects/KotlinStudy/app/src/test/java/com/example/kotlinstudy/s5/ExamleUnitTest5.kt")
        val result: Boolean = files.run {
            readText().contains("test3") //readText()一次性全部加载进来
//            "xxx"
        }
        println(result) //true

        //2
        val result1: Boolean = "The people's Republic of China.".run(::isLong)
        println(result1)

        //3具有传递性的链式调用
        "The people's Republic of China.".run(::isLong).run(::showMessage).run(::print)

    }

    fun isLong(name: String) = name.length >= 10
    fun showMessage(isLong: Boolean): String {
        return if (isLong) {
            "Name is too long."
        } else "Please rename"
    }

    @Test
    //with 传参的方式不一样，很少用
    fun test4() {
        "The people's Republic of China.".run { length >= 10 }
        with("The people's Republic of China.") { length >= 10 }
    }

    @Test
    //also 和let一样也是把接收者作为值参传递给lambda,但是有一点不同：also返回接收者对象，而let返回lambda结果。
    //针对这一特性，also特别适合同一原始对象  做链式调用
    fun test5() {
        //紧接着第二行可以初始化
        var fileContents: List<String>
        File("/Volumes/1T/StudioProjects/KotlinStudy/app/src/test/java/com/example/kotlinstudy/s5/ExamleUnitTest5.kt")
            .also {
                it.name
            }.also {
                fileContents = it.readLines()
            }
        println(fileContents)
    }

    @Test
    //takeIf 需要结合判断lambda中的条件表达式 给出的是true或者false,  true返回接收者对象， false返回null
    fun test6() {
        val readText =
            File("/Volumes/1T/StudioProjects/KotlinStudy/app/src/test/java/com/example/kotlinstudy/s5/ExamleUnitTest5.kt")
                .takeIf { it.exists() && it.canRead() }
                ?.readText()
        println(readText)

    }

    @Test
    //takeUnless 和6刚好相反
    fun test7() {
        val readText =
            File("/Volumes/1T/StudioProjects/KotlinStudy/app/src/test/java/com/example/kotlinstudy/s5/ExamleUnitTest5.kt")
                .takeUnless { it.isHidden }
                ?.readText()
        println(readText)
    }

    @Test

    //
    fun test8() {
        var last = ""
        var current = ""
        runBlocking {
            flow<String> {
                for (i in 1..100000) {
//                    File("/Users/mac/Desktop/BBIN/BBIN完整/log/20211106log.txt")
                    File("D:\\迅雷下载\\BBIN\\log\\20211113log.txt")
                        .takeIf { !it.isHidden }
                        ?.readLines()
                        ?.filter { it.isNotBlank() && it.contains("A桌") }
                        ?.let {
                            current = it[it.lastIndex]
                            if (current != last) {
                                emit(current)
                                last = current
                            }
                        }
                    delay(300)
                }
            }.collect {
                println("${it}")
            }
        }

    }
}